package com.yfp.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfp.client.domain.AiModelConfig;
import com.yfp.client.domain.AiModelService;
import com.yfp.client.domain.vo.AiModelConfigVO;
import com.yfp.client.domain.vo.AiModelServiceInfoVO;
import com.yfp.client.mapper.AiModelServiceMapper;
import com.yfp.client.service.AiModelConfigService;
import com.yfp.client.service.AiModelServiceService;
import com.yfp.client.util.SecurityUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.math.BigDecimal;
import java.util.Objects;
import java.util.Optional;

/**
 *
 * @description 针对表【ai_model_service(AI模型服务表)】的数据库操作Service实现
 * @createDate 2025-02-25 15:10:18
 */
@Slf4j
@Service
public class AiModelServiceServiceImpl extends ServiceImpl<AiModelServiceMapper, AiModelService> implements AiModelServiceService {

    @Resource
    private AiModelServiceMapper aiModelServiceMapper;
    @Resource
    private AiModelConfigService aiModelConfigService;
    @Resource
    private OpenAiChatModel openAiChatModel;
    @Resource
    private ChatClient chatClient;
    @Resource
    private ChatMemory mychatMemory;

    @Override
    public AiModelServiceInfoVO searchActiveModel() {

        AiModelService aiModelService = aiModelServiceMapper.searchActiveModel("silicon-flow");
        if (Objects.isNull(aiModelService)) {
            return null;
        }
        AiModelConfig aiModelConfig = aiModelConfigService.searchActiveModel(aiModelService.getId());
        if (Objects.isNull(aiModelConfig)) {
            return null;
        }

        AiModelServiceInfoVO aiModelServiceInfoVO = BeanUtil.toBean(aiModelService, AiModelServiceInfoVO.class);
        AiModelConfigVO aiModelConfigVO = BeanUtil.toBean(aiModelConfig, AiModelConfigVO.class);

        aiModelServiceInfoVO.setAiModelConfig(aiModelConfigVO);
        return aiModelServiceInfoVO;
    }

    @Override
    public String chatCall(String message) {
        String clientId = SecurityUtils.getClientId();
        // 获取当前 激活 模型的配置信息
        AiModelServiceInfoVO aiModelServiceInfoVO = this.searchActiveModel();
        // 构造 模型 调用配置信息
        OpenAiChatOptions chatOptions = this.buildChatOptionsConfig(aiModelServiceInfoVO);
        OpenAiApi openAiApi = this.buildOpenAiApiConfig(aiModelServiceInfoVO);

        ChatModel build = OpenAiChatModel.builder().openAiApi(openAiApi).defaultOptions(chatOptions).build();
        ChatClient.ChatClientRequestSpec chatClient = this.buildChatClient(message, build, aiModelServiceInfoVO, clientId);

        String text = chatClient.call().content();
        return text;
    }

    @Override
    public Flux<String> chatStream(String message) {
        String clientId = SecurityUtils.getClientId();
        // 获取当前 激活 模型的配置信息
        AiModelServiceInfoVO aiModelServiceInfoVO = this.searchActiveModel();
        // 构造 模型 调用配置信息
        OpenAiChatOptions chatOptions = this.buildChatOptionsConfig(aiModelServiceInfoVO);
        OpenAiApi openAiApi = this.buildOpenAiApiConfig(aiModelServiceInfoVO);

        ChatModel build = OpenAiChatModel.builder().openAiApi(openAiApi).defaultOptions(chatOptions).build();
        ChatClient.ChatClientRequestSpec chatClient = this.buildChatClient(message, build, aiModelServiceInfoVO, clientId);

        Flux<String> stringFlux = chatClient.stream().chatResponse().map(chatResponse -> {
                    return Optional.ofNullable(chatResponse.getResult().getOutput().getText()).orElse("");
                })
                // 异常时，与前端约定的字符 "服务超时"
                .onErrorReturn("服务超时");
        return stringFlux;
    }

    private ChatClient.ChatClientRequestSpec buildChatClient(String message, ChatModel build, AiModelServiceInfoVO aiModelServiceInfoVO, String clientId) {
        ChatClient chatClient = ChatClient.create(build).mutate()
                .defaultSystem("你是'AI饭宝'智能机器人")
                .defaultSystem("你的名字叫'AI饭宝'智能机器人,服务于'麦德范'平台，是'杭州范式生活服务有限公司'开发的一款智能客服。可以解决用户在购买餐品时遇到的问题。")
                .defaultAdvisors(new MessageChatMemoryAdvisor(mychatMemory))
                .build();
        ChatClient.ChatClientRequestSpec chatClientRequestSpec = chatClient.prompt().user(message)
                .advisors(new SimpleLoggerAdvisor())
                .advisors(adv -> adv
                        .param(MessageChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, aiModelServiceInfoVO.getAiModelConfig().getContextLength())
                        .param(MessageChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, clientId));
        return chatClientRequestSpec;
    }

    @Override
    public OpenAiChatOptions buildChatOptionsConfig(AiModelServiceInfoVO aiModelServiceInfoVO) {
        if (Objects.isNull(aiModelServiceInfoVO)) {
            throw new RuntimeException("AI恰宝下班啦！请稍后重试~");
        }

        String modelName = aiModelServiceInfoVO.getAiModelConfig().getName();
        BigDecimal temperature = aiModelServiceInfoVO.getAiModelConfig().getTemperature();
        BigDecimal topP = aiModelServiceInfoVO.getAiModelConfig().getTopP();
        Integer thoughtChainLength = aiModelServiceInfoVO.getAiModelConfig().getThoughtChainLength();

        OpenAiChatOptions chatOptions = OpenAiChatOptions.builder()
                .model(modelName)
                .temperature(temperature.doubleValue())
                .topP(topP.doubleValue())
                .build();

        return chatOptions;
    }

    @Override
    public OpenAiApi buildOpenAiApiConfig(AiModelServiceInfoVO aiModelServiceInfoVO) {
        if (Objects.isNull(aiModelServiceInfoVO)) {
            throw new RuntimeException("AI恰宝下班啦！请稍后重试~");
        }

        String apiUrl = aiModelServiceInfoVO.getApiUrl();
        String apiKey = aiModelServiceInfoVO.getApiKey();

        OpenAiApi openAiApi = OpenAiApi.builder()
                .baseUrl(apiUrl)
                .apiKey(apiKey)
                .build();

        return openAiApi;
    }
}




